import math
import os
import sys
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QMessageBox, QProgressBar, QPushButton, QWidget, QDialog
from PyQt5.QtCore import QBasicTimer

from yangke.common.config import logger
from yangke.common.qt import YkWindow, run_app, YkInputPanel, YkDialog
from cal_CHP_4抽凝 import set_value, isNum, in_range1, in_range2, get_minp_by_h1, get_maxp_by_h1, \
    get_minp_by_h2, get_maxp_by_h2, cost, A1, A2, A3, A4
from yangke.base import fit_surface
from pyecharts import options as opts
from pyecharts.charts import Pie
from pyecharts.faker import Faker


class MainWindow(YkWindow):  # 从YkWindow继承父类
    def __init__(self):
        global icon_file
        icon_file = os.path.join(os.path.dirname(__file__), "ui", "yk.png")
        super(MainWindow, self).__init__()  # 父类初始化方法
        # self.setGeometry(0, 0, 1400, 800)  # 窗口尺寸
        self.setWindowIcon(QIcon(icon_file))

        self.enable_table()  # 表格弹出
        self.enable_input_panel()  # 面板弹出
        self.setWindowTitle("国投钦州发电有限公司热电负荷优化分配计算软件")  # 软件名称
        self.panel1 = YkInputPanel(from_file="ui/ui_panel_setcurve1.yaml")  # 定义面板
        self.panel2 = YkInputPanel(from_file="ui/ui_panel_setcurve2.yaml")
        self.panel3 = YkInputPanel(from_file="ui/ui_panel_setcurve3.yaml")
        self.panel4 = YkInputPanel(from_file="ui/ui_panel_setcurve4.yaml")
        if self._root_splitter is not None:
            self._root_splitter.setSizes([400, 800])  # 窗口尺寸
        self.statusBar1.showMessage("作者：何欣欣")
        # self.center()
        self.progress = QProgressBar()
        self.progress.setMaximum(100)
        self.progress.setMinimum(0)
        self.statusBar1.addPermanentWidget(self.progress)


    def cal_CHP(self):
        a1 = self.panel1.get_values_and_units(need_unit=False)  # 从面板读取能耗曲线
        a2 = self.panel2.get_values_and_units(need_unit=False)
        a3 = self.panel3.get_values_and_units(need_unit=False)
        a4 = self.panel4.get_values_and_units(need_unit=False)
        x0 = self.get_value_of_panel(need_unit=False, need_dict=False)  # 从面板读取数据x[0]
        a1 = [float(x) for x in a1]
        a2 = [float(x) for x in a2]
        a3 = [float(x) for x in a3]
        a4 = [float(x) for x in a4]
        x0 = [int(x) for x in x0]
        p_demand, h_demand, p1, p2, p3, p4, h1, h2, h3, h4, dp1, dp2 = x0
        # p_demand = int(p_demand)
        # h_demand = int(h_demand)
        # p1 = int(p1)
        # p2 = int(p2)
        # p3 = int(p3)
        # p4 = int(p4)
        # h1 = int(h1)
        # h2 = int(h2)
        # h3 = int(h3)
        # h4 = int(h4)
        # dp1 = int(dp1)
        # dp2 = int(dp2)
        p_total = p1 + p2 + p3 + p4
        h_total = h1 + h2 + h3 + h4
        if not in_range1(p1, h1):
            QMessageBox.information(self, "警告", "1号机组参数不在热电可行域", QMessageBox.Yes)
            return 0
        if not in_range2(p2, h2):
            QMessageBox.information(self, "警告", "2号机组参数不在热电可行域", QMessageBox.Yes)
            return 0
        if p_total != p_demand:
            QMessageBox.information(self, "警告", "电功率不匹配", QMessageBox.Yes)
            return 0
        if h_total != h_demand:
            QMessageBox.information(self, "警告", "供热流量不匹配", QMessageBox.Yes)
            return 0
        if dp1 > 100 or dp1 < 0:
            QMessageBox.information(self, "警告", "600MW机组调节范围超限（区间：0~100MW）", QMessageBox.Yes)
            return 0
        if dp2 > 100 or dp1 < 0:
            QMessageBox.information(self, "警告", "1000MW机组调节范围超限（区间：0~100MW）", QMessageBox.Yes)
            return 0
        # i = isNum(p1) + isNum(p2) + isNum(p3) + isNum(p4)
        # if i != 4:
        #     QMessageBox.information(self, "警告", "请输入4台机组电功率", QMessageBox.Yes)
        #     return 0

        # if p1 in range(1, 450):
        #     QMessageBox.information(self, "警告", "1号机组无法供热", QMessageBox.Yes)
        # else:
        #     return 0
        # if p2 in range(1, 450):
        #     QMessageBox.information(self, "警告", "2号机组无法供热", QMessageBox.Yes)
        # else:
        #     return 0
        # if p3 in range(1, 700):
        #     QMessageBox.information(self, "警告", "3号机组无法供热", QMessageBox.Yes)
        # else:
        #     return 0
        # if p4 in range(1, 700):
        #     QMessageBox.information(self, "警告", "4号机组无法供热", QMessageBox.Yes)
        # else:
        #     return 0
        _ = self.calculate(p_demand, h_demand, p1, p2, p3, p4, h1, h2, h3, h4, dp1, dp2, a1, a2, a3, a4)
        min_p1, min_p2, min_p3, min_p4, min_h1, min_h2, min_h3, min_h4, min_c1, min_c2, min_c3, min_c4, cost0 = _
        cost_total = min_c1 + min_c2 + min_c3 + min_c4

        self._table_widget.set_value("优化结果.当前全厂发电煤耗", set_value(cost0, 1))
        self._table_widget.set_value("优化结果.优化后全厂发电煤耗", set_value(cost_total, 1))
        self._table_widget.set_value("优化结果.节能量", set_value(cost0 - cost_total, 1))
        self._table_widget.set_value("1号机组.电功率", set_value(min_p1))
        self._table_widget.set_value("2号机组.电功率", set_value(min_p2))
        self._table_widget.set_value("3号机组.电功率", set_value(min_p3))
        self._table_widget.set_value("4号机组.电功率", set_value(min_p4))
        self._table_widget.set_value("1号机组.供热流量", set_value(min_h1))
        self._table_widget.set_value("2号机组.供热流量", set_value(min_h2))
        self._table_widget.set_value("3号机组.供热流量", set_value(min_h3))
        self._table_widget.set_value("4号机组.供热流量", set_value(min_h4))
        self._table_widget.set_value("1号机组.发电煤耗", set_value(min_c1, 1))
        self._table_widget.set_value("2号机组.发电煤耗", set_value(min_c2, 1))
        self._table_widget.set_value("3号机组.发电煤耗", set_value(min_c3, 1))
        self._table_widget.set_value("4号机组.发电煤耗", set_value(min_c4, 1))

        # dia = QDialog(self)
        # dia.setWindowTitle("对话框")
        # dia.resize(800,600)
        # dia.exec()

    def set_curve1(self):  # ===================================================1号机组能耗曲线设置窗口
        self.panel1.setWindowIcon(QIcon(icon_file))
        self.panel1.setWindowTitle("1号机组能耗曲线设置")
        self.panel1.show()

    def confirm_curve1(self):
        self.panel1.close()

    def set_curve2(self):  # ===================================================2号机组能耗曲线设置窗口
        self.panel2.setWindowIcon(QIcon(icon_file))
        self.panel2.setWindowTitle("2号机组能耗曲线设置")
        self.panel2.show()

    def confirm_curve2(self):
        self.panel2.close()

    def set_curve3(self):  # ===================================================3号机组能耗曲线设置窗口
        self.panel3.setWindowIcon(QIcon(icon_file))
        self.panel3.setWindowTitle("3号机组能耗曲线设置")
        self.panel3.show()

    def confirm_curve3(self):
        self.panel3.close()

    def set_curve4(self):  # ===================================================4号机组能耗曲线设置窗口
        self.panel4.setWindowIcon(QIcon(icon_file))
        self.panel4.setWindowTitle("4号机组能耗曲线设置")
        self.panel4.show()

    def confirm_curve4(self):
        self.panel4.close()

    def yk_signal_received(self, msg: dict):
        self.progress.setValue(msg.get("i"))
        # QApplication.processEvents()

    def calculate(self, p_total=0, h_total=0, p1=660, p2=660, p3=1000, p4=1000, h1=0, h2=0, h3=0, h4=0, dp1=10, dp2=10, a1=[],
                  a2=[], a3=[], a4=[]):
        interval = 1
        price_p = 50  # 电价
        price_h = 200  # 热价
        p10 = p1
        p20 = p2
        p30 = p3
        p40 = p4
        cost1 = cost(a1, p1, h1)  # 根据能耗特性曲线计算能耗
        cost2 = cost(a2, p2, h2)
        cost3 = cost(a3, p3, h3)
        cost4 = cost(a4, p4, h4)
        cost0 = cost1 + cost2 + cost3 + cost4
        profit1 = p1 * price_p + h1 * price_h - cost1
        profit2 = p2 * price_p + h2 * price_h - cost2
        profit3 = p3 * price_p + h3 * price_h - cost3
        profit4 = p4 * price_p + h4 * price_h - cost4
        profit0 = profit1 + profit2 + profit3 + profit4
        min_cost = 10000000
        min_p1, min_p2, min_p3, min_p4 = 0, 0, 0, 0
        min_h1, min_h2, min_h3, min_h4 = 0, 0, 0, 0
        min_c1, min_c2, min_c3, min_c4 = 0, 0, 0, 0
        profit1, profit2, profit3, profit4 = 0, 0, 0, 0

        # =================================================================1号机组循环
        if p1 == 0:  # 设置1号机组热负荷循环上下限,如果停机则不循环
            h1max = 1
        else:
            h1max = h_total + 1
        h1max = min(h1max, 180)  # 手动定义1号机组最大热负荷
        i = 0
        for h1 in range(0, h1max, interval):  # 调试进度条
            if p1 == 0:  # 设置1号机组电功率循环上下限,如果停机则不循环
                p1min = 0
                p1max = 1
            else:
                # if int(get_minp_by_h1(h1)) > p10 - dp1:  # 用dp1和h1限制1号机组电功率循环上下限
                #     p1min = int(get_minp_by_h1(h1))
                # else:
                #     p1min = p10 - dp1
                # if math.ceil(min(get_maxp_by_h1(h1), p_total)) + 1 < p10 + dp1:
                #     p1max = math.ceil(min(get_maxp_by_h1(h1), p_total)) + 1
                # else:
                #     p1max = p10 + dp1
                p1min = max(p10 - dp1, int(get_minp_by_h1(h1)))
                p1max = min(math.ceil(min(get_maxp_by_h1(h1), p_total)) + 0.1, p10 + dp1)

            i = i + 1
            # self.yk_signal.emit({"i": i})
            self.progress.setValue(i)
            if i > 100:
                i = 0

            for p1 in range(p1min, p1max, interval):
                # =================================================================2号机组循环
                if p2 == 0:
                    h2max = 1
                else:
                    h2max = h_total - h1
                h2max = int(min(h2max, 136))  # 手动输入2号机组最大热负荷

                for h2 in range(0, h2max, interval):
                    if p2 == 0:  # 设置2号机组电功率循环上下限,如果停机则不循环
                        p2min = 0
                        p2max = 1
                    else:
                        # if int(get_minp_by_h2(h2)) > p20 - dp1:  # 用dp1和h2限制2号机组电功率循环上下限
                        #     p2min = int(get_minp_by_h2(h2))
                        # else:
                        #     p2min = p20 - dp1
                        # if int(min(get_maxp_by_h2(h2), p_total - p1)) < p20 + dp1:
                        #     p2max = int(min(get_maxp_by_h2(h2), p_total - p1)) + 1
                        # else:
                        #     p2max = p20 + dp1
                        p2min = max(int(get_minp_by_h2(h2)), p20 - dp1)
                        p2max = min(math.ceil(min(get_maxp_by_h2(h2), p_total - p1)) + 1, p20 + dp1)

                    for p2 in range(p2min, p2max, interval):
                        # =================================================================3号机组循环
                        p3 = p_total - p1 - p2
                        h3 = 0
                        h4 = h_total - h1 - h2
                        p4 = 0
                        # if p1 == 0:
                        #     cost1 = 0
                        # else:
                        #     cost1 = cost(A1, p1, h1)
                        # if p2 == 0:
                        #     cost2 = 0
                        # else:
                        #     cost2 = cost(A2, p2, h2)
                        # =================================================================成本计算
                        cost1 = cost(A1, p1, h1)
                        cost2 = cost(A2, p2, h2)
                        cost3 = cost(A3, p3, h3)
                        cost4 = cost(A4, p4, h4)
                        cost_total = cost1 + cost2 + cost3 + cost4
                        # profit1 = p1 * price_p + h1 * price_h - cost1
                        # profit2 = p2 * price_p + h2 * price_h - cost2
                        # profit3 = p3 * price_p + h3 * price_h - cost3
                        # profit4 = p4 * price_p + h4 * price_h - cost4
                        # profit_total = profit1 + profit2 + profit3 + profit4

                        QApplication.processEvents()
                        # =================================================================最小成本/最大利润方法计算
                        if cost_total < min_cost:
                            min_cost = cost_total
                            min_p1 = p1
                            min_h1 = h1
                            min_p2 = p2
                            min_h2 = h2
                            min_p3 = p3
                            min_h3 = h3
                            min_p4 = p4
                            min_h4 = h4
                            min_c1 = cost1
                            min_c2 = cost2
                            min_c3 = cost3
                            min_c4 = cost4
                        # if profit_total > min_cost:
                        #     min_cost = cost_total
                        #     min_p1 = p1
                        #     min_h1 = h1
                        #     min_p2 = p2
                        #     min_h2 = h2
                        #     min_p3 = p3
                        #     min_h3 = h3
                        #     min_p4 = p4
                        #     min_h4 = h4
                        #     min_c1 = profit1
                        #     min_c2 = profit2
                        #     min_c3 = profit3
                        #     min_c4 = profit4
        self.progress.setValue(0)
        return min_p1, min_p2, min_p3, min_p4, min_h1, min_h2, min_h3, min_h4, min_c1, min_c2, min_c3, min_c4, cost0


if __name__ == "__main__":  # 执行以下程序
    run_app(MainWindow)
